#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <utility>


using std::pair;
using std::map;
using std::set;
using std::ifstream;
using std::ofstream;
using std::istringstream;
using std::ostringstream;
using std::string;
using std::vector;
using std::cout;
using std::cin;
using std::endl;

class Dict {
public://公有成员函数
    //查找单词并输出词频、行号、原始行
    void serch_word(const string& word_, const string& filename) {
        //将文件读进词典
        read_file_in_dict(filename);
        //将大写转小写
        string word(word_);
        for (auto& e : word) {
            change_big_to_little(e);
        }
        //查找词频
        auto it_frequency = m_frequency.find(word);
        //如果不存在这个单词
        if (it_frequency == m_frequency.end()) {
            cout << word << "occurs 0 times" << endl;
            return;
        }
        //单词存在
        cout << word << "occurs " << it_frequency->second << " times" << endl;
        auto& linenum_set = m_word_linenum[word];
        for (auto& e : linenum_set) {
            cout << "(line : " << e << ")";
            cout << m_line[e - 1] << endl;
        }
    }

private://私有成员函数
    //判断是不是字母
    bool is_char(char ch) {
        return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
    }
    //判断字符是不是大写字母
    bool is_big_char(char ch) {
        return ch >= 'A' && ch <= 'Z';
    }
    //将大写字母转换成小写字母，小写不变
    int change_big_to_little(char& ch) {
        if (is_big_char(ch)) {
            ch += 'a' - 'A';
        }
        return 0;
    }
    //更新word，删掉不是字母的，并将大写转小写
    string& update_word(string& word) {
        auto it = word.begin();
        while (it < word.end()) {
            //先将大写转小写
            change_big_to_little(*it);
            //删除非字母
            if (is_char(*it) == false) {
                it = word.erase(it);
                continue;
            }
            it++;
        }
        return word;
    }
    //如果这个单词不是空字符串，插入m_word_linenum更新行号
    int update_word_linenum(const string& word, int line_num) {
        if (!word.empty()) {
            m_word_linenum[word].insert(line_num);
        }
        return 0;
    }
    //如果这个单词不是空字符串,插入m_frequency,更新词频
    int update_frequency(const string& word) {
        if (!word.empty()) {
            m_frequency[word]++;
        }
        return 0;
    }
    //读取文件，并写入字典对象
    int read_file_in_dict(const string& filename) {
        //读文件
        ifstream ifs(filename);
        if (!ifs) {
            cout << "open " << filename << "failed" << endl;
        }
        //保存一行
        string line;
        //记录行号
        int line_num = 1;
        //循环读取文件,每次读一行
        while (std::getline(ifs, line)) {
            //先存进m_line保留原始行
            m_line.push_back(line);
            //对行开始解析
            string word;
            istringstream iss(line);
            while (iss >> word) {
                //更新word，删掉不是字母的，并将大写转小写
                update_word(word);
                //如果这个单词不是空字符串，插入m_word_linenum更新行号
                update_word_linenum(word, line_num);
                //如果这个单词不是空字符串,插入m_frequency,更新词频
                update_frequency(word);
            }
            line_num++;
        }
        return 0;
    }
private://私有的数据成员
    vector<string> m_line;//按行存储原始行
    map<string, set<int>> m_word_linenum;//存储字符串所对应的行号
    map<string, int> m_frequency;//存储字符串的词频
};//end of class 


void test() {
    Dict dict;
    string word;
    while (cout << "请输入需要搜索的单词:" << endl, cin >> word) {
        dict.serch_word(word, "china_daily.txt");
    }

}
int main() {
    test();
    return 0;
}